#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include "easysock.hpp"

namespace proto
{
struct request
{
    request() 
    {}
    request(int x, char op, int y) : _x(x), _y(y), _op(op) 
    {}
    request(const std::string& str) { deserialize(str); }

    std::string serialize() 
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;
        return Json::FastWriter().write(root);
    }

    void deserialize(const std::string& req)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(req, root);
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = (char)root["op"].asInt();
    }

    int _x, _y;
    char _op;
};

struct response
{
    response()
    {}
    response(int res, int st) : _res(res), _st(st) 
    {}

    std::string serialize() 
    {
        Json::Value root;
        root["res"] = _res;
        root["st"] = _st;
        return Json::FastWriter().write(root);
    }

    void deserialize(const std::string& rsp)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(rsp, root);
        _res = root["res"].asInt();
        _st = root["st"].asInt();
    }

    int _res, _st;
};

static int parserapack(std::string& buf, std::string* req)
{
    int b = 0;
    for (int e = 0; e < buf.size(); e++)
    {
        if (buf[e] == '\n') 
        {
            *req = buf.substr(b, e + 1);
            buf.erase(b, e + 1);

            b = e + 1;
            return req->size();
        }
    }

    return -1;
}

static int recvapack(int sock, std::string* msg)
{
    while (true)
    {
        char ch;

        ssize_t s = inet::api::Recv(sock, &ch, sizeof(ch));
        if (s <= 0)
            return s;

        msg->push_back(ch);
        if (ch == '\n') 
            break;
    }

    return msg->size();
}

}
